#include "rtweekend.h"

const double infinity = std::numeric_limits<double>::infinity();
const double pi = 3.1415926535897932385;

double degrees_to_radians(double degrees)
{
	return degrees * pi / 180.0;
}

double random_double()
{
	return std::rand() / (RAND_MAX + 1.0);
}

double random_double(double min, double max)
{
	return min + (max - min) * random_double();
}

int random_int(int min, int max)
{
	// Returns a random integer in [min,max].
	return int(random_double(min, max + 1));
}

vec3 random_unit_vector()
{
	while (true) {
		auto p = vec3::random(-1, 1);
		auto lensq = p.length_squared();
		if (1e-160 < lensq && lensq <= 1)
			return p / sqrt(lensq);
	}
}

vec3 random_on_hemisphere(const vec3& normal)
{
	vec3 on_unit_sphere = random_unit_vector();
	if (dot(on_unit_sphere, normal) > 0.0) // In the same hemisphere as the normal
		return on_unit_sphere;
	else
		return -on_unit_sphere;
}

vec3 reflect(const vec3& v, const vec3& n)
{
	return v - 2 * dot(v, n) * n;
}

vec3 refract(const vec3& r, const vec3& n, double etai_over_etat)
{
	auto cos_theta = std::fmin(dot(-r, n), 1.0);
	vec3 r_out_perp = etai_over_etat * (r + cos_theta * n);
	vec3 r_out_parallel = -std::sqrt(std::fabs(1.0 - r_out_perp.length_squared())) * n;
	return r_out_perp + r_out_parallel;
}

inline vec3 random_in_unit_disk()
{
	while (true) {
		auto p = vec3(random_double(-1, 1), random_double(-1, 1), 0);
		if (p.length_squared() < 1)
			return p;
	}
}
// 逆变换采样生成的随机向量，详情推导请见: 7.3 Cosine Sampling a Hemisphere
vec3 random_cosine_direction()
{
	auto r1 = random_double();
	auto r2 = random_double();

	auto phi = 2 * pi * r1;
	auto x = std::cos(phi) * std::sqrt(r2);
	auto y = std::sin(phi) * std::sqrt(r2);
	auto z = std::sqrt(1 - r2);

	return vec3(x, y, z);
}
